#include "Class.h"
#include "Student.h"
#include "Staff.h"
#include "Teacher.h"
#include <fstream>


void Class::saveToFile(char* filename)
{
	ofstream fs;
	fs.open(filename);
	PrintInfo(fs);
	fs.flush();
}
void Class::loadFile(char* filename)
{

}

void Class::PrintInfo(ostream &out)
{

	Node* cur = head;
	while (cur)
	{
		out << "=======================" << endl;
		cur->Data->PrintInfo(out);
		cur = cur->next;
	}
}
void Class::PrintInfo()
{
	Node* cur = head;
	while (cur)
	{
		cout << "=======================" << endl;
		cur->Data->PrintInfo();
		cur = cur->next;
	}
}

void Class::PrintStudentInfo(int score)
{

	Node* cur = head;
	while (cur)
	{
		Student* std = dynamic_cast<Student*>(cur->Data);
		if (std && std->getAverageScore() > score)
		{
			cout << "=======================" << endl;
			cur->Data->PrintInfo();
		}
		cur = cur->next;
	}
}

void Class::sort()
{
	Node::merge_sort(head, compare);
}

void Class::AddPeople(People* &people)
{
	Node* element = new Node;
	element->Data = people;
	Node::add(head, element);
}

Class::~Class()
{
	Node* cur = head;
	while (cur)
	{
		head = cur->next;
		delete cur;
		cur = head;
	}
}

int Class::compare( Node*& node1,  Node*& node2)
{
	if (!node1)
		return 0;
	if (!node2)
		return 1;
	int a = node1->Data->getType(), b=node2->Data->getType();
	return (a > b);
}

void Node::add(Node* &head, Node* &element)
{
	element->next = head;
	head = element;
}

void Node::addData(Node* &head, People* people)
{
	Node* element = new Node;
	element->Data = (People*) people->Clone();
	element->next = 0;
	if (!head)
		head = element;
	else
	{
		Node* cur = head;
		while (cur->next)
			cur = cur->next;
		cur->next = element;
	}
}

void Node::remove(Node* &head)
{
	Node* cur;
	while (cur = head)
	{
		head = cur->next;
		delete cur;
	}
}


Node::~Node()
{
	delete Data;
}

Class::Class()
{
	head = 0;
}
//Sorting
void Node::merge_sort(Node* &head,  int (*compare)( Node*&,  Node*&))
{
	if (!head || !head->next)
		return;
	Node* head2;
	head2 = split_half(head);
	merge_sort(head, compare);
	merge_sort(head2, compare);
	head = merge(head, head2, compare);
}
Node* Node::split_half(Node* head)
{
	if (head == 0 || head->next == 0)
		return 0;
	Node* cur = head, *cur2 = head, *cur3 = 0;
	while (cur && cur->next)
	{
		cur3 = cur2;
		cur2 = cur2->next;
		cur = cur->next->next;
	}
	cur3->next = 0;
	return cur2;
}
Node* Node::merge(Node* head1, Node* head2,  int (*compare)(Node*&,  Node*&))
{
	Node* cur1 = head1,* cur2 = head2;
	Node* newHead = 0;
	while (cur1 || cur2)
	{
		if (compare(cur1, cur2))
		{
			addData(newHead, cur1->Data);
			cur1 = cur1->next;
		}
		else
		{
			addData(newHead, cur2->Data);
			cur2 = cur2->next;
		}
	}

	// Make new head
	remove(head1);
	remove(head2);
	return newHead;
}
